home *** CD-ROM | disk | FTP | other *** search
/ Merciful 2 / Merciful - Disc 2.iso / software / d / devioustools25.dms / devioustools25.adf / utils / 003.lzx / AMountains / calcalt.c < prev    next >
C/C++ Source or Header  |  2004-02-13  |  21KB  |  764 lines

  1. /************************************************************************/
  2. /* Recursive update procedure for fractal landscapes                    */
  3. /*                                                                        */
  4. /* The only procedures needed outside this file are                        */
  5. /*                                                                        */
  6. /*    make_fold,        called once to initialise the data structs.            */
  7. /*    next_strip,        each call returns a new strip off the side of the    */
  8. /*                    surface -  you can keep calling this as often as    */
  9. /*                    you want.                                            */
  10. /*    free_strip,        get rid of the strip when finished with it.            */
  11. /*    free_fold,        get rid of the data structs when finished with this    */
  12. /*                    surface.                                            */
  13. /*                                                                        */
  14. /* Apart  from  make_fold  all these routines get their parameters from    */
  15. /* their  local Fold struct, make_fold initialises all these values and    */
  16. /* has  to get it right for the fractal to work.  If you want to change    */
  17. /* the  fractal  dim in mid run you will have to change values at every    */
  18. /* level.   each  recursive  level  only calls the level below once for    */
  19. /* every  two  times  it  is  called itself so it will take a number of    */
  20. /* iterations  for any changes to be notices by the bottom (long length    */
  21. /* scale) level.                                                        */
  22. /************************************************************************/
  23.  
  24. #include <proto/dos.h>
  25.  
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <m68881.h>
  29. #include <math.h>
  30.  
  31. #include "crinkle.h"
  32.  
  33. static Strip *make_strip( int );
  34. static void free_strip( Strip *);
  35. static Strip *double_strip( Strip *);
  36. static Strip *set_strip( int, Height );
  37. static void x_update( int, double, double, Strip *, Strip *, Strip * );
  38. static void p_update( int, double, double, Strip *, Strip *, Strip * );
  39. static void t_update( int, double, double, Strip *, Strip *, Strip * );
  40. static void v_update( int, double, double, Strip *, Strip *, Strip * );
  41. static void vside_update( int, double, double, Strip * );
  42. static void hside_update( int, double, double, Strip *, Strip *, Strip * );
  43.  
  44. static Strip *make_strip( int level )
  45. {
  46.     Strip    *p;
  47.     int        points;
  48.  
  49.     p = (Strip *) malloc( sizeof(Strip) );
  50.     if( p == NULL ) {
  51.         PutStr( "make_strip: malloc failed\n" );
  52.         exit( 1 );
  53.     }
  54.     p->level    = level;
  55.     points        = (1 << level) + 1;
  56.     p->d        = (Height *) malloc( points * sizeof(Height) );
  57.     if( p->d == NULL ) {
  58.         PutStr( "make_strip: malloc failed\n" );
  59.         exit( 1 );
  60.     }
  61.     return p;
  62. }
  63.  
  64. static void free_strip( Strip *p )
  65. {
  66.     if( p->d ) {
  67.         free( p->d );
  68.         p->d = NULL;
  69.     }
  70.     free( p );
  71. }
  72.  
  73. static Strip *double_strip( Strip *s )
  74. {
  75.     Strip    *p;
  76.     Height    *a, *b;
  77.     int        i;
  78.  
  79.     p = make_strip( s->level + 1 );
  80.     a = s->d;
  81.     b = p->d;
  82.     for( i = 0; i < ( 1 << s->level ); i++ ) {
  83.         *b++    = *a++;
  84.         *b        = 0.0;
  85.         b++;
  86.     }
  87.     *b = *a;
  88.     return p;
  89. }
  90.  
  91. static Strip *set_strip( int level, Height value )
  92. {
  93.     int        i;
  94.     Strip    *s;
  95.     Height    *h;
  96.  
  97.     s = make_strip( level );
  98.     h = s->d;
  99.     for( i = 0; i < ( ( 1 << level ) + 1 ); i++ ) {
  100.         *h++ = value;
  101.     }
  102.     return s;
  103. }
  104.  
  105. /* -------------------------------------------------------------------- */
  106. /* Initialise the fold structures.                                        */
  107. /* As  everything  else reads the parameters from their fold structs we    */
  108. /* need to set these here,                                                */
  109. /*                                                                        */
  110. /*    p        is the parameter struct common to all update levels.        */
  111. /*    levels    is the number of levels of recursion below this one.        */
  112. /*    Number of points = 2^levels+1                                        */
  113. /*    stop    is the number of levels that are generated as random        */
  114. /*            offsets from a constant rather than from an average.        */
  115. /*    fractal_start,                                                        */
  116. /*            if true we start in the middle of a mountain range            */
  117. /*            if false we build up mountains from the start height.        */
  118. /*    length    is the length of the side of the square at this level.        */
  119. /*            N.B this means the update square NOT the width of the        */
  120. /*            fractal.                                                    */
  121. /*    len        gets smaller as the level increases.                        */
  122. /*    start,    the starting height for a non-fractal start.                */
  123. /* -------------------------------------------------------------------- */
  124.  
  125. Fold *make_fold( Parm *param, int levels, int stop, Length length )
  126. {
  127.     Fold    *p;
  128.     Length    scale, midscale;
  129.     double    root2;
  130.     int i;
  131.  
  132.   if( ( levels < stop ) || ( stop < 0 ) ) {
  133.         Printf(
  134.             "make_fold: invalid parameters\n"
  135.             "make_fold: levels = %ld , stop = %ld \n",
  136.             levels,
  137.             stop
  138.         );
  139.         exit( 1 );
  140.     }
  141.     p = (Fold *) malloc( sizeof(Fold) );
  142.     if( p == NULL ) {
  143.         PutStr( "make_fold: malloc failed\n" );
  144.         exit( 1 );
  145.     }
  146.     root2        = sqrt( 2.0 );
  147.     scale        = pow( length, 2.0 * param->fdim );
  148.     midscale    = pow( length * root2, 2.0 * param->fdim );
  149.     p->level    = levels;
  150.     p->stop        = stop;
  151.     p->state    = START;
  152.     p->save        = NULL;
  153.     p->p        = param;
  154.     p->scale    = scale;
  155.     p->midscale    = midscale;
  156.     for( i = 0; i < NSTRIP; i++ ) {
  157.         p->s[i] = NULL;
  158.     }
  159.     if( levels > stop ) {
  160.         p->next = make_fold( param, levels - 1, stop, 2.0 * length );
  161.     }
  162.     else {
  163.         p->next = NULL;
  164.     }
  165.     return p;
  166. }
  167.  
  168. void free_fold( Fold *f )
  169. {
  170.     int    i;
  171.     for ( i = 0; i < NSTRIP; i++ ) {
  172.         if( f->s[i] != NULL ) {
  173.             free_strip( f->s[i] );
  174.             f->s[i] = NULL;
  175.         }
  176.     }
  177.     free( f );
  178. }
  179.  
  180. Strip *next_strip( Fold *fold )
  181. {
  182.     Strip    *result = NULL;
  183.     Strip    *tmp;
  184.     Strip    **t;
  185.     int        i, count, iter;
  186.  
  187.     count = ( 1 << fold->level ) + 1;
  188.     if( fold->level == fold->stop ) {
  189.  
  190.         /* ------------------------------------------------------------ */
  191.         /* generate values from scratch                                    */
  192.         /* ------------------------------------------------------------ */
  193.  
  194.         result = make_strip( fold->stop );
  195.         for( i = 0; i < count; i++ ) {
  196.             result->d[i] = fold->p->mean + fold->scale * gaussian();
  197.         }
  198.     }
  199.     else {
  200.  
  201.         /* ------------------------------------------------------------ */
  202.         /* There are two types of strip,                                */
  203.         /*                                                                */
  204.         /* A strips -    generated by the lower recursion layers.        */
  205.         /*                 these contain the corner points and half the    */
  206.         /*                side points                                        */
  207.         /* B strips -    added by this layer, this contains the mid        */
  208.         /*                points and half the side points.                */
  209.         /*                                                                */
  210.         /* The various update routines test for NULL pointer arguments    */
  211.         /* so that this routine will not fail while filling the            */
  212.         /* pipeline.                                                    */
  213.         /* ------------------------------------------------------------ */
  214.  
  215.         while( result == NULL ) {
  216.  
  217.             /* -------------------------------------------------------- */
  218.             /* iterate                                                    */
  219.             /* -------------------------------------------------------- */
  220.  
  221.             switch( fold->state ) {
  222.  
  223.                 /* ---------------------------------------------------- */
  224.                 /* perform an update. return first result                */
  225.                 /* ---------------------------------------------------- */
  226.  
  227.                 case START:
  228.                     t = fold->s;
  229.  
  230.                     /* ------------------------------------------------ */
  231.                     /* read in a new A strip at the start of the        */
  232.                     /* pipeline                                            */
  233.                     /* ------------------------------------------------ */
  234.  
  235.                     tmp        = next_strip( fold->next );
  236.                     t[0]    = double_strip( tmp );
  237.                     free_strip( tmp );
  238.  
  239.                     /* ------------------------------------------------ */
  240.                     /* make the new B strip                                */
  241.                     /* ------------------------------------------------ */
  242.  
  243.                     t[1] = set_strip( fold->level, 0.0 );
  244.                     if( ! t[2] ) {
  245.  
  246.                         /* -------------------------------------------- */
  247.                         /* we want to have an A B A pattern of strips    */
  248.                         /* at the start of the pipeline.                */
  249.                         /* force this when starting the pipe            */
  250.                         /* -------------------------------------------- */
  251.  
  252.                         t[2]    = t[0];
  253.                         tmp        = next_strip( fold->next );
  254.                         t[0]    = double_strip( tmp );
  255.                         free_strip( tmp );
  256.                     }
  257.  
  258.                     /* ------------------------------------------------ */
  259.                     /* create the mid point                                */
  260.                     /* t := A B A                                        */
  261.                     /* ------------------------------------------------ */
  262.  
  263.                     x_update( count, fold->midscale, 0.0, t[0], t[1], t[2] );
  264.  
  265.                     if( fold->p->rg1 ) {
  266.  
  267.                         /* -------------------------------------------- */
  268.                         /* first possible regeneration step                */
  269.                         /* use the midpoints to regenerate the corner    */
  270.                         /* values increment t by 2 so we still have and    */
  271.                         /* A B A pattern                                */
  272.                         /* -------------------------------------------- */
  273.  
  274.                         v_update( count, fold->midscale, fold->p->midmix, t[1], t[2], t[3] );
  275.                         t += 2;
  276.                     }
  277.  
  278.                     /* ------------------------------------------------ */
  279.                     /* fill in the edge points                            */
  280.                     /* increment t by 2 to preserve the A B A pattern    */
  281.                     /* ------------------------------------------------ */
  282.  
  283.                     if( fold->p->cross ) {
  284.                         t_update( count, fold->scale, 0.0, t[0], t[1], t[2] );
  285.                         p_update( count, fold->scale, 0.0, t[1], t[2], t[3] );
  286.                         t += 2;
  287.                     }
  288.                     else {
  289.                         hside_update( count, fold->scale, 0.0, t[0], t[1], t[2] );
  290.                         vside_update( count, fold->scale, 0.0, t[2] );
  291.                         t += 2;
  292.                     }
  293.  
  294.                     if(fold->p->rg2) {
  295.  
  296.                         /* -------------------------------------------- */
  297.                         /* second regeneration step update midpoint        */
  298.                         /* from the new edge values                        */
  299.                         /*--------------------------------------------- */
  300.  
  301.                         if( fold->p->cross ) {
  302.                             p_update( count, fold->scale, fold->p->mix, t[0], t[1], t[2] );
  303.                         }
  304.                         else {
  305.                             vside_update( count, fold->scale, fold->p->mix, t[1] );
  306.                         }
  307.                     }
  308.  
  309.                     /* ------------------------------------------------ */
  310.                     /* increment t by 1                                    */
  311.                     /* this gives a B A B pattern to regen - 3            */
  312.                     /* if regen 3 is not being used it leaves t            */
  313.                     /* pointing to the 2 new result strips                */
  314.                     /* ------------------------------------------------ */
  315.  
  316.                     t++;
  317.  
  318.                     if( fold->p->rg3 ) {
  319.  
  320.                         /* -------------------------------------------- */
  321.                         /* final regenration step                        */
  322.                         /* regenerate the corner points from the new    */
  323.                         /* edge values this needs a B A B pattern leave    */
  324.                         /* t pointing to the 2 new result strips        */
  325.                         /*                                                */
  326.                         /* this has to be a t_update                    */
  327.                         /* -------------------------------------------- */
  328.  
  329.                         t_update( count, fold->scale, fold->p->mix, t[0], t[1], t[2] );
  330.                         t++;
  331.                     }
  332.                     result        = t[1];
  333.                     fold->save    = t[0];
  334.                     t[0]        =
  335.                     t[1]        = NULL;
  336.                     fold->state    = STORE;
  337.                     break;
  338.  
  339.                 /* ---------------------------------------------------- */
  340.                 /* return second value from previous update.            */
  341.                 /* ---------------------------------------------------- */
  342.  
  343.                 case STORE:
  344.                     result        = fold->save;
  345.                     fold->save    = NULL;
  346.                     for( i = NSTRIP - 1; i > 1; i-- ) {
  347.                         fold->s[i] = fold->s[i-2];
  348.                     }
  349.                     fold->s[0]    =
  350.                     fold->s[1]    = NULL;
  351.                     fold->state    = START;
  352.                     break;
  353.  
  354.                 default:
  355.                     Printf(
  356.                         "next_strip: invalid state level %ld state %ld\n",
  357.                         fold->level,
  358.                         fold->state
  359.                     );
  360.                     exit(3);
  361.             }
  362.         }
  363.      }
  364.     iter = fold->level - fold->stop;
  365.     if( fold->p->force_front > iter ) {
  366.         result->d[0] = fold->p->forceval;
  367.     }
  368.     if( fold->p->force_back > iter ) {
  369.         result->d[count-1] = fold->p->forceval;
  370.     }
  371.     return result;
  372. }
  373.  
  374. static void x_update( int count, double scale, double mix, Strip *a, Strip *b, Strip *c )
  375. {
  376.     int        i;
  377.     double    w;
  378.     Height    *mp, *lp, *rp;
  379.  
  380.     /* ---------------------------------------------------------------- */
  381.     /* don't run unless we have all the parameters                        */
  382.     /* ---------------------------------------------------------------- */
  383.  
  384.     if( !a || !c ) return;
  385.     if( !b ) {
  386.         PutStr( "x_update: attempt to update NULL strip\n" );
  387.         exit( 1 );
  388.     }
  389.  
  390.     w    = ( 1.0 - mix ) / 4.0;
  391.     mp    = b->d;
  392.     lp    = a->d;
  393.     rp    = c->d;
  394.  
  395.     if( mix <= 0.0 ) {
  396.  
  397.         /* ------------------------------------------------------------ */
  398.         /* random offset to average of new points                        */
  399.         /* ------------------------------------------------------------ */
  400.  
  401.         for ( i = 0; i < count - 2; i += 2 ) {
  402.             mp[1] = 0.25 * ( lp[0] + rp[0] + lp[2] + rp[2] ) + scale * gaussian();
  403.             mp += 2;
  404.             lp += 2;
  405.             rp += 2;
  406.         }
  407.     }
  408.     else if ( mix >= 1.0 ) {
  409.  
  410.         /* ------------------------------------------------------------ */
  411.         /* random offset to old value                                    */
  412.         /* ------------------------------------------------------------ */
  413.  
  414.         for ( i = 0; i < count - 2; i += 2 ) {
  415.             mp[1] += scale * gaussian();
  416.             mp += 2;
  417.             lp += 2;
  418.             rp += 2;
  419.         }
  420.     }
  421.     else {
  422.  
  423.         /* ------------------------------------------------------------ */
  424.         /* mixed update                                                    */
  425.         /* ------------------------------------------------------------ */
  426.  
  427.         for ( i = 0; i < count - 2; i += 2 ) {
  428.             mp[1] = mix * mp[1] + w * ( lp[0] + rp[0] + lp[2] + rp[2] ) + scale * gaussian();
  429.             mp += 2;
  430.             lp += 2;
  431.             rp += 2;
  432.         }
  433.     }
  434. }    
  435.  
  436. static void p_update( int count, double scale, double mix, Strip *a, Strip *b, Strip *c )
  437. {
  438.     int        i;
  439.     double    w;
  440.     Height    *mp, *lp, *rp;
  441.  
  442.     /* ---------------------------------------------------------------- */
  443.     /* don't run if we have no parameters                                */
  444.     /* ---------------------------------------------------------------- */
  445.  
  446.     if( !a || !b ) return;
  447.  
  448.     /* ---------------------------------------------------------------- */
  449.     /* if c is missing we can do a vside update instead                    */
  450.     /* should really be a sideways t but what the heck we only need        */
  451.     /* this at the start                                                */
  452.     /* ---------------------------------------------------------------- */
  453.  
  454.     if( !c ) {
  455.         vside_update( count, scale, mix, b );
  456.         return;
  457.     }
  458.  
  459.     w    = ( 1.0 - mix ) / 4.0;
  460.     mp    = b->d;
  461.     lp    = a->d;
  462.     rp    = c->d;
  463.  
  464.     if( mix <= 0.0 ) {
  465.  
  466.         /* ------------------------------------------------------------ */
  467.         /* random offset to average of new points                        */
  468.         /* ------------------------------------------------------------ */
  469.  
  470.         for( i = 0; i < count - 2; i += 2 ) {
  471.             mp[1] = 0.25 * ( lp[1] + rp[1] + mp[0] + mp[2] ) + scale * gaussian();
  472.             mp += 2;
  473.             lp += 2;
  474.             rp += 2;
  475.         }
  476.     }
  477.     else if ( mix >= 1.0 ) {
  478.  
  479.         /* ------------------------------------------------------------ */
  480.         /* random offset to old values                                    */
  481.         /* ------------------------------------------------------------ */
  482.  
  483.         for ( i = 0; i < count - 2; i += 2 ) {
  484.             mp[1] += scale * gaussian();
  485.             mp += 2;
  486.             lp += 2;
  487.             rp += 2;
  488.         }
  489.     }
  490.     else {
  491.  
  492.         /* ------------------------------------------------------------ */
  493.         /* mixed update                                                    */
  494.         /* ------------------------------------------------------------ */
  495.  
  496.         for ( i = 0; i < count - 2; i += 2 ) {
  497.             mp[1] = mix * mp[1] + w * ( lp[1] + rp[1] + mp[0] + mp[2] ) + scale * gaussian();
  498.             mp += 2;
  499.             lp += 2;
  500.             rp += 2;
  501.         }
  502.     }
  503. }    
  504.  
  505. static void t_update( int count, double scale, double mix, Strip *a, Strip *b, Strip *c )
  506. {
  507.     int        i;
  508.     double    w, we;
  509.     Height    *mp, *lp, *rp;
  510.  
  511.     /* ---------------------------------------------------------------- */
  512.     /* don't run unless we have all the parameters                        */
  513.     /* ---------------------------------------------------------------- */
  514.  
  515.     if( !a || !c ) return;
  516.     if( !b ) {
  517.         PutStr( "t_update: attempt to update NULL strip\n" );
  518.         exit( 1 );
  519.     }
  520.  
  521.     w    = ( 1.0 - mix ) / 4.0;
  522.     we    = ( 1.0 - mix ) / 3.0;
  523.     mp    = b->d;
  524.     lp    = a->d;
  525.     rp    = c->d;
  526.  
  527.     if( mix <= 0.0 ) {
  528.  
  529.         /* ------------------------------------------------------------ */
  530.         /* random offset to average of new points                        */
  531.         /* ------------------------------------------------------------ */
  532.  
  533.         mp[0] = ( 1.0 / 3.0 ) * ( lp[0] + rp[0] + mp[1] ) + scale * gaussian();
  534.         mp++;
  535.         lp++;
  536.         rp++;
  537.         for( i = 1; i < count - 3; i += 2 ) {
  538.             mp[1] = 0.25 * ( lp[1] + rp[1] + mp[0] + mp[2] ) + scale * gaussian();
  539.             mp += 2;
  540.             lp += 2;
  541.             rp += 2;
  542.         }
  543.         mp[1] = ( 1.0 / 3.0 ) * ( lp[1] + rp[1] + mp[0] ) + scale * gaussian();
  544.     }
  545.     else if ( mix >= 1.0 ) {
  546.  
  547.         /* ------------------------------------------------------------ */
  548.         /* random offset to old values                                    */
  549.         /* ------------------------------------------------------------ */
  550.  
  551.         for( i = 0; i < count - 2; i += 2 ) {
  552.             mp[0] += scale * gaussian();
  553.             mp += 2;
  554.             lp += 2;
  555.             rp += 2;
  556.         }
  557.     }
  558.     else {
  559.  
  560.         /* ------------------------------------------------------------ */
  561.         /* mixed update                                                    */
  562.         /* ------------------------------------------------------------ */
  563.  
  564.         mp[0] = mix * mp[0] + we * ( lp[0] + rp[0] + mp[1] ) + scale * gaussian();
  565.         mp++;
  566.         lp++;
  567.         rp++;
  568.         for ( i = 1; i < count - 3; i += 2 ) {
  569.             mp[1] = mix * mp[1] + w * ( lp[1] + rp[1] + mp[0] + mp[2] ) + scale * gaussian();
  570.             mp += 2;
  571.             lp += 2;
  572.             rp += 2;
  573.         }
  574.         mp[1] = mix * mp[1] + we * ( lp[1] + rp[1] + mp[0] ) + scale * gaussian();
  575.     }
  576. }    
  577.  
  578. static void v_update( int count, double scale, double mix, Strip *a, Strip *b, Strip *c )
  579. {
  580.     int i;
  581.     double w, we;
  582.     Height *mp, *lp, *rp;
  583.  
  584.     /* ---------------------------------------------------------------- */
  585.     /* don't run unless we have all the parameters                        */
  586.     /* ---------------------------------------------------------------- */
  587.  
  588.     if( !a || !c ) return;
  589.     if( !b ) {
  590.         PutStr( "v_update: attempt to update NULL strip\n" );
  591.         exit( 1 );
  592.     }
  593.  
  594.     w    = ( 1.0 - mix ) / 4.0;
  595.     we    = ( 1.0 - mix ) / 2.0;
  596.     mp    = b->d;
  597.     lp    = a->d;
  598.     rp    = c->d;
  599.  
  600.     if ( mix <= 0.0 ) {
  601.  
  602.         /* ------------------------------------------------------------ */
  603.         /* random offset of average of new points                        */
  604.         /* ------------------------------------------------------------ */
  605.  
  606.         mp[0] = 0.5 * ( lp[1] + rp[1] ) + scale * gaussian();
  607.         mp++;
  608.         lp++;
  609.         rp++;
  610.         for( i = 1; i < count - 3; i += 2 ) {
  611.             mp[1] = 0.25 * ( lp[0] + rp[0] + lp[2] + rp[2] ) + scale * gaussian();
  612.             mp += 2;
  613.             lp += 2;
  614.             rp += 2;
  615.         }
  616.         mp[1] = 0.5 * ( lp[0] + rp[0] ) + scale * gaussian();
  617.     }
  618.     else if( mix >= 1.0 ) {
  619.  
  620.         /* ------------------------------------------------------------ */
  621.         /* random offset to old values                                    */
  622.         /* ------------------------------------------------------------ */
  623.  
  624.         for( i = 0; i < count - 2; i += 2 ) {
  625.             mp[0] += scale * gaussian();
  626.             mp += 2;
  627.             lp += 2;
  628.             rp += 2;
  629.         }
  630.     }
  631.     else {
  632.  
  633.         /* ------------------------------------------------------------ */
  634.         /* mixed update                                                    */
  635.         /* ------------------------------------------------------------ */
  636.  
  637.         mp[0] = mix * mp[0] + we * ( lp[1] + rp[1] ) + scale * gaussian();
  638.         mp++;
  639.         lp++;
  640.         rp++;
  641.         for( i = 1; i < count - 3; i += 2 ) {
  642.             mp[1] = mix * mp[1] + w * ( lp[0] + rp[0] + lp[2] + rp[2] ) + scale * gaussian();
  643.             mp += 2;
  644.             lp += 2;
  645.             rp += 2;
  646.         }
  647.         mp[1] = mix * mp[1] + we * ( lp[0] + rp[0] ) + scale * gaussian();
  648.     }
  649. }    
  650.  
  651. static void vside_update( int count, double scale, double mix, Strip *a )
  652. {
  653.     int        i;
  654.     double    w;
  655.     Height    *mp;
  656.  
  657.     /* ---------------------------------------------------------------- */
  658.     /* don't run unless we have all the parameters                        */
  659.     /* ---------------------------------------------------------------- */
  660.  
  661.     if( !a ) return;
  662.  
  663.  
  664.     w    = ( 1.0 - mix ) / 2.0;
  665.     mp    = a->d;
  666.  
  667.     if ( mix <= 0.0 ) {
  668.  
  669.         /* ------------------------------------------------------------ */
  670.         /* random offset to average of new points                        */
  671.         /* ------------------------------------------------------------ */
  672.  
  673.         for ( i = 0; i < count - 2; i += 2 ) {
  674.             mp[1] = 0.5 * ( mp[0] + mp[2] ) + scale * gaussian();
  675.             mp += 2;
  676.         }
  677.     }
  678.     else if ( mix >= 1.0 ) {
  679.  
  680.         /* ------------------------------------------------------------ */
  681.         /* random offset to old values                                    */
  682.         /* ------------------------------------------------------------ */
  683.  
  684.         for( i = 0; i < count - 2; i += 2 ) {
  685.             mp[1] += scale * gaussian();
  686.             mp += 2;
  687.         }
  688.     }
  689.     else {
  690.  
  691.         /* ------------------------------------------------------------ */
  692.         /* mixed update                                                    */
  693.         /* ------------------------------------------------------------ */
  694.  
  695.         for ( i = 0; i < count - 2; i += 2 ) {
  696.             mp[1] = mix * mp[1] + w * ( mp[0] + mp[2] ) + scale * gaussian();
  697.             mp += 2;
  698.         }
  699.     }
  700. }    
  701.  
  702.  
  703. static void hside_update( int count, double scale, double mix, Strip *a, Strip *b, Strip *c )
  704. {
  705.     int        i;
  706.     double    w;
  707.     Height    *mp, *lp, *rp;
  708.  
  709.     /* ---------------------------------------------------------------- */
  710.     /* don't run unless we have all the parameters                        */
  711.     /* ---------------------------------------------------------------- */
  712.  
  713.     if ( !a || !c ) return;
  714.     if ( !b ) {
  715.         PutStr( "x_update: attempt to update NULL strip\n" );
  716.         exit( 1 );
  717.     }
  718.  
  719.     w    = ( 1.0 - mix ) / 2.0;
  720.     mp    = b->d;
  721.     lp    = a->d;
  722.     rp    = c->d;
  723.  
  724.     if ( mix <= 0.0 ) {
  725.  
  726.         /* ------------------------------------------------------------ */
  727.         /* random offset to average of new points                        */
  728.         /* ------------------------------------------------------------ */
  729.  
  730.         for ( i = 0; i < count; i += 2 ) {
  731.             mp[0] = 0.5 * ( lp[0] + rp[0] ) + scale * gaussian();
  732.             mp += 2;
  733.             lp += 2;
  734.             rp += 2;
  735.         }
  736.     }
  737.     else if ( mix >= 1.0 ) {
  738.  
  739.         /* ------------------------------------------------------------ */
  740.         /* random offset to old points                                    */
  741.         /* ------------------------------------------------------------ */
  742.  
  743.         for ( i = 0; i < count; i += 2 ) {
  744.             mp[0] += scale * gaussian();
  745.             mp += 2;
  746.             lp += 2;
  747.             rp += 2;
  748.         }
  749.     }
  750.     else {
  751.  
  752.         /* ------------------------------------------------------------ */
  753.         /* mixed update                                                    */
  754.         /* ------------------------------------------------------------ */
  755.  
  756.         for ( i = 0; i < count; i += 2 ) {
  757.             mp[0] = mix * mp[0] + w * ( lp[0] + rp[0] ) + scale * gaussian();
  758.             mp += 2;
  759.             lp += 2;
  760.             rp += 2;
  761.         }
  762.     }
  763. }    
  764.